package com.mindskip.xzs.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mindskip.xzs.domain.dto.admin.education.SubjectCreateDTO;
import com.mindskip.xzs.domain.dto.admin.education.SubjectPageDTO;
import com.mindskip.xzs.domain.entity.Subject;
import com.mindskip.xzs.domain.vo.admin.education.SubjectVO;
import com.mindskip.xzs.repository.BaseMapper;
import com.mindskip.xzs.repository.SubjectMapper;
import com.mindskip.xzs.service.SubjectService;
import com.mindskip.xzs.utility.BeanCopyUtils;
import com.mindskip.xzs.utility.PageInfoUtil;
import com.mindskip.xzs.utility.RedisCache;
import com.mindskip.xzs.utility.RedisConstants;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class SubjectServiceImpl extends BaseServiceImpl<Subject> implements SubjectService {

    private final SubjectMapper subjectMapper;

    private final RedisCache redisCache;


    public SubjectServiceImpl(BaseMapper<Subject> baseMapper, SubjectMapper subjectMapper, RedisCache redisCache) {
        super(baseMapper);
        this.subjectMapper = subjectMapper;
        this.redisCache = redisCache;
    }

    @Override
    public List<Subject> selectAll() {

        // 从 redis 中查询商铺缓存
        List<Subject> subjectList = redisCache.getCacheList(RedisConstants.SUBJECT_LIST_KEY);

        // 判断缓存是否存在
        if (!ObjectUtils.isEmpty(subjectList)) {
            // 存在，直接返回
            return subjectList;
        }

        // 不存在，则从数据库中查询数据
        List<Subject> subjects = subjectMapper.selectAll();
        if (ObjectUtils.isEmpty(subjects)) {
            // 数据库中查询不到，则抛出异常
            throw new RuntimeException("学科列表不存在");
        }

        // 从数据库中查询到数据不为空，则将数据写入到 redis 中
        Long aLong = redisCache.setCacheList(RedisConstants.SUBJECT_LIST_KEY, subjects);
        if (aLong == null) {
            throw new RuntimeException("redis失效");
        }
        // 设置过期时间
        redisCache.expire(RedisConstants.SUBJECT_LIST_KEY, RedisConstants.CACHE_SUBJECT_TTL, TimeUnit.MINUTES);

        return subjects;
    }

    @Override
    public PageInfo<SubjectVO> getSubjectByPage(SubjectPageDTO subjectPageDTO) {

        //自动的对PageHelper.startPage 方法下的第一个sql查询进行分页，给其拼接sql语句
        PageHelper.startPage(subjectPageDTO.getPageIndex(), subjectPageDTO.getPageSize(), "id desc");
        List<Subject> subjectList = subjectMapper.selectByPage(subjectPageDTO);
        PageInfo<Subject> oldPageInfo = new PageInfo<>(subjectList);

        // 将 List<Subject> 转为 List<SubjectVO>
        List<SubjectVO> subjectVOList = oldPageInfo.getList()
                .stream()
                .map(new Function<Subject, SubjectVO>() {
                    @Override
                    public SubjectVO apply(Subject subject) {
                        SubjectVO subjectVO = new SubjectVO();
                        BeanUtils.copyProperties(subject, subjectVO);
                        return subjectVO;
                    }
                }).collect(Collectors.toList());

        // 将 oldPageInfo 中的所有属性赋值到 PageInfo<SubjectVO> 对象，并更改该对象的List属性为 subjectVOList
        return PageInfoUtil.copyMap(oldPageInfo, subjectVOList);
    }

    // 插入或者更新学科
    @Override
    public void insertOrUpdateSubject(SubjectCreateDTO subjectCreateDTO) {
        Subject subject = new Subject();
        BeanUtils.copyProperties(subjectCreateDTO, subject);

        if (subjectCreateDTO.getId() == null) {
            // id 为空，则代表是创建学科
            subjectMapper.insertSelective(subject);

        }else {
            // id 不为空，则代表是修改学科
            subjectMapper.updateByPrimaryKeySelective(subject);
        }
    }

    // 软删除
    @Override
    public void softDelete(Integer id) {
        Subject subject = subjectMapper.selectByPrimaryKey(id);
        if (subject == null) {
            throw new RuntimeException("无法查询到数据");
        }
        subject.setDeleted(true);
        subjectMapper.updateByPrimaryKeySelective(subject);
    }

    @Override
    public List<com.mindskip.xzs.domain.vo.student.education.SubjectVO> getSubjectVOByLevel(Integer level) {

        List<Subject> subjectList = subjectMapper.selectByLevel(level);

        return BeanCopyUtils.copyBeanList(subjectList, com.mindskip.xzs.domain.vo.student.education.SubjectVO.class);
    }

    @Override
    public Subject selectById(Integer id) {
        // 防止缓存穿透
        Subject subject = redisCache.queryWithPassThrough(RedisConstants.SUBJECT_KEY, id,
                Subject.class, integer -> SubjectServiceImpl.super.selectById(id), RedisConstants.CACHE_SUBJECT_TTL, TimeUnit.MINUTES);
        if (ObjectUtils.isEmpty(subject)) {
            throw new RuntimeException("查询到的subject为null");
        }

        return subject;
    }
}
